#include <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// 信号处理函数：打印调用栈并退出
void handle_crash(int signum) {
    fprintf(stderr, "收到信号 %d，程序崩溃！调用栈：\n", signum);

    // 步骤1：分配缓冲区存储栈帧地址（最多64个栈帧）
    const int MAX_FRAMES = 64;
    void *buffer[MAX_FRAMES];
    int frame_count = backtrace(buffer, MAX_FRAMES);

    // 步骤2：将栈帧地址转换为可读信息并输出（使用backtrace_symbols_fd更安全）
    backtrace_symbols_fd(buffer, frame_count, STDERR_FILENO);

    // 退出程序
    exit(1);
}

// 测试函数：模拟调用链
void func3() {
    // 触发段错误（故意访问非法地址）
    *(int*)0 = 0;
}

void func2() {
    func3(); // 调用func3
}

void func1() {
    func2(); // 调用func2
}

int main() {
    // 注册信号处理函数：捕获段错误、浮点数异常等信号
    signal(SIGSEGV, handle_crash);
    signal(SIGFPE, handle_crash);

    func1(); // 启动调用链
    return 0;
}